#include "../views.hpp"

using lms::views::OrderView;

OrderView::OrderView() {
    init();
}

OrderView::OrderView(Queue<Customer>* customers) {
    init();
    this->customers = customers;
}

void OrderView::init() {
    UnitOfWork& unitOfWork = UnitOfWork::getInstance();
    bookServices = unitOfWork.GetBookServices();
    orderServices = unitOfWork.GetOrderServices();
    retrievedBook = null;
}

void OrderView::showBooks() {
    if (bookServices != null) {
        Node< Book >* first = (bookServices->get())->getFirst();
        int index = 0;
        while (first != null) {
            Book* temp = first->getData();
            cout << "\t" << ++index << "- " << temp->getTitle() << " -- " << temp->getAuthor() << " -- " << temp->getPrice() << endl;
            first = first->getNext();
        }
    }
}

void OrderView::showAllOrders() {

    if (orderServices != null) {

        LinkedList< Order >* orders = orderServices->getOrders();
        if (orders != null) {
            Node< Order >* first = orders->getFirst();
            while (first != null) {
                Order* order = first->getData();


                showBillInfo(order->getCustomer());
                showOrdersDetail(order->getOrderDetails());

                first = first->getNext();
                cout << endl << endl;
            }

        }
    }
}

void OrderView::showActualOrder() {
    if (orderServices != null) {

        Order* actualOrder = orderServices->getActualOrder();

        if (actualOrder != null) {
            showBillInfo(actualOrder->getCustomer());
            showOrdersDetail(actualOrder->getOrderDetails());
            Utilities::printText("------------------------------------------------------");
            cout << endl << " Total.: $" << (orderServices->getActualOrder())->getTotalCost() << endl;
        }
    }
    cout<< endl;
}

void OrderView::setCustomersEnQueue(Queue<Customer>* customers) {
    this->customers = customers;
}

void OrderView::showOrdersDetail(LinkedList<OrderDetail>* orderDetails) {
    if (orderDetails != null) {

        Node< OrderDetail >* first = orderDetails->getFirst();
        cout << "\n Number\t Amount\t Book Name\t Book Price\t" << endl;
        int index = 0;
        while (first != null) {

            OrderDetail* temp = first->getData();
            Book* book = temp->getPurchasedBook();

            cout << ++index << ".\t " << temp->getBookAmountPerUnit() << "\t " << book->getTitle() << "\t " << book->getPrice() << endl;
            first = first->getNext();
        }
    }
}

void OrderView::showBillInfo(Customer* customer) {
    if (customer != null) {
        cout << "\nCustomer.: " << customer->getFullName() << endl;
    }
}

void OrderView::mainMenu() {
    do {
        Utilities::clearScreen();
        Utilities::printText("\t Books Shop");
        Utilities::printText("\n\t1. Attend Customer");
        Utilities::printText("\n\t2. List History.");
        Utilities::printText("\n\t3. Back.");

        option = Utilities::reinterpret_input<int>("\n\tChoose an option.");
        switch (option) {
            case 1:
                Utilities::clearScreen();
                if (orderServices != null && customers != null){
                    orderServices->setCustomerOrder((customers->deQueue())->getData());
                show();
        }
                else
                {
                    Utilities::printText("There are not Customers in the Queue\n");
                }
                
                break;
            case 2:
                Utilities::clearScreen();
                showAllOrders();
                Utilities::pause();
                break;
            default:
                break;
        }
    } while (option != 3);
}

void OrderView::addBook()
{
    
    showBooks();
    cout << endl << endl;
    productIndex = Utilities::reinterpret_input< int >(" Choose a book number.: ");
    --productIndex;

    retrievedBook = (bookServices->get())->getByIndex(productIndex);
    quantity = Utilities::reinterpret_input<int>(" Type The Quantity: ");

    if (retrievedBook != null)
        orderServices->addBook(retrievedBook, quantity);
}

void OrderView::removeBook()
{
    showActualOrder();
    Utilities::printText("");
    productIndex = Utilities::reinterpret_input<int>(" Choose a book number.: ");
    --productIndex;

    orderServices->removeBook(productIndex);    
}

void OrderView::checkOut()
{
    orderServices->checkout();
    Utilities::printText("\tOrder checked.");
    Utilities::pause();
}

void OrderView::cancelOrder()
{
    Utilities::printText("Do You Want To Cancel\n");
    showActualOrder();
    option = Utilities::reinterpret_input<int>("Choose 1 For Cancel Or 2 For No");
    if (option == 1) {
    orderServices->cancel();
    Utilities::printText("\tOrder canceled.");
   }
}

void OrderView::show() {

    do {
        Utilities::clearScreen();
        Utilities::printText("\t\t Orders Management\n");
        Utilities::printText("\t1. Add Book: \n");
        Utilities::printText("\t2. Remove Book\n");
        Utilities::printText("\t3. Check Out: \n");
        Utilities::printText("\t4. Cancel Order: \n");
        Utilities::printText("\t5. List Order: \n");
        Utilities::printText("\t6. Back. \n");
        option = Utilities::reinterpret_input<int>("\t Choose The Option: ");

        
        switch (option) {
            case 1:
                Utilities::clearScreen();
                addBook();
                break;

            case 2:
                Utilities::clearScreen();
                removeBook();
                break;
                
            case 3:
                Utilities::clearScreen();
                checkOut();
                break;
                
            case 4:
                Utilities::clearScreen();
                cancelOrder();
                break;
                
            case 5:
                Utilities::clearScreen();
                showActualOrder();
                Utilities::printText("\n");
                Utilities::pause();
                break;
                
            case 6:
                break;
                
            default:
                Utilities::printText("\tInvalid Option\n");
                Utilities::pause();
                break;
        }

    } while (option != 6);

}


